#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <assert.h>
#include <memory.h>

#include "configure.h"
#include "mem_pool.h"
#include "config.h"
#include "dbg.h"

typedef struct ring_pool {
	uint32_t 	item_size;
	uint32_t 	max_count;
        uint32_t       	pos;
        uint32_t       	count;
        mem_pool_t *    mem_pool;
	void *		pool_buf;
	void *		reserved;
        void *      	array[0];
} ring_pool_t;

typedef struct ring {
	uint32_t 	item_size;
	uint32_t 	max_count;
        uint32_t       	pos;
        uint32_t       	count;
        mem_pool_t *    mem_pool;
        void *      	array[0];
} ring_t;

//for high speed io.
void *ring_pool_create(const char *name, size_t count, size_t ele_size)
{
	int i;

	mem_pool_t * mem_pool = mem_pool_get(MEMORY_TYPE_INDEX_RING); 
	
	ring_pool_t *ring_pool = mem_pool_alloc(mem_pool, sizeof(ring_pool_t) + count * sizeof(void *)); 
	ring_pool->pool_buf = huge_tls_malloc(count * ele_size);//mem_pool_alloc(mem_pool, count * ele_size); 

	assert(ring_pool->pool_buf);

        ring_pool->mem_pool = mem_pool;
	ring_pool->max_count = count;
	ring_pool->item_size = ele_size;
	ring_pool->pos = 0;
	ring_pool->count = count;

	for(i = 0;i<count;i++) {
		ring_pool->array[i] = ring_pool->pool_buf + i * ele_size;
	}

	return ring_pool;
}

void ring_pool_free(void *ring_ptr)
{
        ring_pool_t *ring_pool= ring_ptr;
	//mem_pool_t *mem_pool = mem_pool_get(MEMORY_TYPE_INDEX_RING);

        huge_tls_free(ring_pool->pool_buf);
	//mem_pool_free(mem_pool, ring_pool->pool_buf);
	mem_pool_free(ring_pool->mem_pool, ring_pool);
}

void ring_pool_push(void *ring_ptr, void **items, uint32_t count)
{
        ring_pool_t *ring = ring_ptr;
	uint32_t i,pos;

        for (i = 0; i < count; i++) {
                pos = (ring->pos + ring->count++) % ring->max_count;
                ring->array[pos] = items[i];
        }
}

int ring_pool_pop(void *ring_ptr, void **items, uint32_t count)
{
        ring_pool_t *ring = ring_ptr;
        uint32_t i, pos;

	if(unlikely(ring->count < count)) {
                assert(0);
                return -1;
        }

        for (i = 0; i < count; i++) {
                pos = ring->pos % ring->max_count;
                items[i] = ring->array[pos];
                ring->pos = (ring->pos + 1) % ring->max_count;
                assert(ring->count--);
        }

	return 0;
}

void *ring_create(const char *name, size_t max_count)
{
	mem_pool_t * mem_pool = mem_pool_get(MEMORY_TYPE_INDEX_RING);
	ring_t *ring = mem_pool_alloc(mem_pool, sizeof(ring_t) + max_count * sizeof(void *)); 

        ring->mem_pool = mem_pool;
	ring->max_count = max_count;
	ring->pos = 0;
	ring->count = 0;

	return ring;
}

void ring_free(void *ring_ptr)
{
        ring_t *ring= ring_ptr;

	mem_pool_free(ring->mem_pool, ring);
}

void ring_push(void *ring_ptr, void **items, uint32_t count)
{
        ring_t *ring = ring_ptr;
	uint32_t i,pos;

        for (i = 0; i < count; i++) {
                pos = (ring->pos + ring->count++) % ring->max_count;
                ring->array[pos] = items[i];
                assert(ring->count <= ring->max_count);
        }
}

int ring_pop(void *ring_ptr, void **items, uint32_t count)
{
        ring_t *ring = ring_ptr;
        uint32_t i, pos;

	if(unlikely(ring->count < count))
		return -1;

        for (i = 0; i < count; i++) {
                pos = ring->pos % ring->max_count;
                items[i] = ring->array[pos];
                ring->pos = (ring->pos + 1) % ring->max_count;
                assert(ring->count--);
        }

	return 0;
}